﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection.Emit;
using System.Reflection;

namespace CodeFound
{
    public class Class1
    {
        public static void method1(dynamic obj)
        {
            Console.WriteLine(obj);
        }
        public static void method2(object obj)
        {
            Console.WriteLine(obj);
        }
        public static void method3(int obj)
        {
            Console.WriteLine(obj);
        }
        public static void method4<T>(T t)
        {
            Console.WriteLine(t);
        }
        public static void Run()
        {
            int n = 2;
            method1(n);
            method2(n);
            method3(n);
            method4<int>(n);
            method4<string>("num");
        }
        public delegate void RenderMethod2<T>(T t);
        
        //public static void Main()
        //{
        //    //RenderM<Int32>("/Index.Html", 2);
        //    //RenderType("", typeof(Int32), 2);
        //    create("");
        //    Console.ReadKey();
        //}
        public static MethodInfo GetMethod(string url)
        {
            return typeof(CodeFound.Class1).GetMethod("method3");
        }
        public static IDictionary<string, MethodInfo> methodList = null;

        public delegate void RednerMethod3(Type t,object o);
        public static void RenderType(string key, Type t, object obj)
        {
            DynamicMethod method = new DynamicMethod("Render2", null, new Type[] {typeof(Type),typeof(object) });
            ILGenerator methodIL = method.GetILGenerator();
            methodIL.Emit(OpCodes.Nop);
            methodIL.Emit(OpCodes.Ldarg_0);
            methodIL.Emit(OpCodes.Call, GetMethod(key));
            methodIL.Emit(OpCodes.Ret);
            RednerMethod3 render = (RednerMethod3)method.CreateDelegate(typeof(RednerMethod3));
            render(t,obj);

        }
        public static void RenderM<T>(string key,T t)
        {
                Type parameterType= typeof(T);
                DynamicMethod method = new DynamicMethod(key, null, new Type[] { typeof(T) });
                ILGenerator methodIL = method.GetILGenerator();
                methodIL.Emit(OpCodes.Nop);
                methodIL.Emit(OpCodes.Ldarg_0);
                methodIL.Emit(OpCodes.Call, GetMethod(key));
                methodIL.Emit(OpCodes.Ret);
                var dele = method.CreateDelegate(typeof(RenderMethod2<>).MakeGenericType());
                var render =(RenderMethod2<T>)dele;
                render(t);
            
        }
        public delegate void RenderObject<T>(IAction action, T t);
        public class RenderSS<T>
        {
            public static RenderObject<T> obj;
            public RenderSS(Delegate dg)
            {
                obj = (RenderObject<T>)dg;
            }
                
        }
        public static void create(string url)
        {
            
            AssemblyName name = new AssemblyName("Com.DiQiSoft.Demo");
            AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, System.Reflection.Emit.AssemblyBuilderAccess.RunAndSave);
            ModuleBuilder module = assembly.DefineDynamicModule(name.Name, name.Name + ".dll");
            TypeBuilder tb = module.DefineType("Express", TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit);
            tb.SetParent(typeof(object));
            MethodBuilder mb = tb.DefineMethod("buid", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static);
            var gpars = mb.DefineGenericParameters("T");
            //gpars[0].SetGenericParameterAttributes(GenericParameterAttributes.ReferenceTypeConstraint);
            mb.SetParameters(typeof(IAction),gpars[0]);
            //mb.Invoke()
            mb.SetReturnType(null);
            var ilgen = mb.GetILGenerator();
            ilgen.Emit(OpCodes.Ldarg_0);
            ilgen.Emit(OpCodes.Ldarg_1);
            ilgen.Emit(OpCodes.Call, typeof(CodeFound.Class1).GetMethod("RenderModel"));
            ilgen.Emit(OpCodes.Ret);
            var a = mb.CreateDelegate(typeof(RenderObject<>).GetGenericTypeDefinition());
            assembly.Save("name.dll");
        }
        public static void RenderModel(IAction  action,int t)
        {
            action.Write(t.ToString());
        }
    }
}
